import CoordTransformUtils.CoordTransform;
import lombok.extern.slf4j.Slf4j;
import utilityTools.BaseGeometryUtility;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class Main {
    /**
     * 当前系统运行平台是否是win平台
     */
    private static final boolean isWin = System.getProperty("os.name").toLowerCase().contains("win");
    /**
     * 当前系统是否是Linux平台
     */
    private static final boolean isLinux = System.getProperty("os.name").toLowerCase().indexOf("linux") >= 0;

    public static void main(String[] args) {
        try {
            System.out.println("Maven管理的Java普通项目\n");
            //System.out.println("获取的核心数："+Runtime.getRuntime().availableProcessors());
            //ReadJson myRead=new ReadJson();
            //myRead.readJson("etl-server",
            //        "E:\\3.能力上中台资料_时空数据融合供给能力\\3.安全评估&处理\\" +
            //                "容器安全评估&解决\\时空数据融合供给能力-微服务容器安全扫描结果\\gis-spatialtempor-etl-server-318.json");
            //log日志输出方式测试
            //Exception error = new Exception("出现异常");
            //log.warn("占位符()，问题：{}",error.getMessage(),error);
            //String coord_WGS="113.2362898,21.9053547";
            //Double coord_Lon=Double.valueOf(coord_WGS.split(",")[0]);
            //Double coord_lat=Double.valueOf(coord_WGS.split(",")[1]);
            //String str = "113.2362898,21.9053547;113.2353993,21.9076491;113.2352312,21.9079071;" +
            //        "113.2345464,21.9086146;113.2342782,21.9089879;113.2341989,21.9093424;" +
            //        "113.2342173,21.9101219;113.2345064,21.9118989";
            //double[] coords_BD09 = GPSUtils.wgs84_To_bd09(coord_lat, coord_Lon);
            //System.out.printf("bd09-x:%f", coords_BD09[0]);
            //System.out.println();
            //System.out.printf("bd09-y:%f", coords_BD09[1]);

            //GeojsonOperation gjOperation=new GeojsonOperation();
            //gjOperation.test验证并获取GeoJson字符串的几何();
            //gjOperation.testOpenGeojson();
            //ShpOperation shpOperation=new ShpOperation();
            //shpOperation.test坐标系参数转换问题();
            //shpOperation.test坐标转换02();
//            exeCLITools();
//            针对Java原生理论进行测试
//            JavaOperations javaOperations=new JavaOperations();
//            javaOperations.test获取Jar包路径();
//            javaOperations.test正则表达式验证();
            //javaOperations.test字符串分割();
            //javaOperations.test时间类型的对象();
//            javaOperations.test判断文件类型();
//            javaOperations.test数组传入参数();
//            javaOperations.test删除切片数据();
//            javaOperations.test枚举类型();
//            javaOperations.tmp路径遍历漏洞修复();
//            javaOperations.test加密解密();
//            javaOperations.testXML转换();
//            javaOperations.testListToString();
//            javaOperations.testListDelete();
//            javaOperations.testPointEquals();
//            javaOperations.testUsingHashCode();
//            javaOperations.test二维数组();
//            javaOperations.test计算概率分布();
//            javaOperations.testJava的复制();
//            javaOperations.test除法计算();
//            javaOperations.test度转为弧度();
//            javaOperations.test字符串分割();
//            javaOperations.testImageConversion();
            //针对GeoTools的工具进行测试
            GeotoolsOperation geotoolsOperation = new GeotoolsOperation();
            //geotoolsOperation.test获取shp的原始列();
            //geotoolsOperation.test空间索引H3含义();
            geotoolsOperation.testUseH3_byNearest();
            //geotoolsOperation.test格网分析();
            //geotoolsOperation.test获取PostGIS数据();
//            geotoolsOperation.crsTransform();
//            geotoolsOperation.test获取属性类型();
//            geotoolsOperation.test判断Datastore类型();
//            geotoolsOperation.testGetFileGeojson();
//            geotoolsOperation.testUnion();
//            geotoolsOperation.testGeoOutput();
//            geotoolsOperation.testReadWkt();
//            geotoolsOperation.test空间权重矩阵();
//            geotoolsOperation.calcDistance();
//            geotoolsOperation.testEPSG坐标系();
//            geotoolsOperation.testxy2vector();
//            geotoolsOperation.test几何类型判断();
//            geotoolsOperation.test四叉树空间索引();
//            geotoolsOperation.test普通空间查询();
//            geotoolsOperation.testKdTree索引();
//            geotoolsOperation.test判断String是wkt或geojson();
//            geotoolsOperation.test获取PostGIS数据();
            //针对shp相关的操作测试
//            ShpOperation shpOperation=new ShpOperation();
//            shpOperation.testGetPropertiesNoGeometry();
//            shpOperation.testShpToExcel();
//            shpOperation.testShpEdit();
            //其他测试
//            GDALOperation operation=new GDALOperation();
//            operation.getRasterGeoTransform();
//            operation.getRasterMetadata();
//            operation.testCreateRaster();
//            String pathSLD="E:\\data\\sld06.sld";
//            CreateSLD sld=new CreateSLD();
//            sld.createSLD_Polygon("the_geom",pathSLD);
//            sld.createSLD_Point(pathSLD);
//            CreateSLD3 sld3=new CreateSLD3();
//            sld3.createSLD_Polygon("the_geom",pathSLD);
//            OtherTests tmp=new OtherTests() ;
//            tmp.timeConvert(4,25);
            //测试抽象类调用方法
//            AbstractFather testProtected=new ChildInner01();
//            testProtected.writeData("在main中调用了inner");
//            testProtected=new ChildOuter02();
//            testProtected.writeData("在main中调用了outer");
            //枚举类的使用距离
            //System.out.println(DbType.HDFS.getType());
            //System.out.println(DbType.HDFS.getName());
            //System.out.println(DbType.getDbType(2));
            //网络分析
            //CalcRoadField.calcSpeedTime();
            //CalcRoadField.getGeometryType_Shp();
            //NetworkAnalysis networkAnalysis=new NetworkAnalysis();
            //networkAnalysis.analysisShortestRoute("gml_id","v2_layer_road_pg.467543","v2_layer_road_pg.590251",0);
            //networkAnalysis.analysisShortestRoute("OBJECTID","2198","2180",0);
            //networkAnalysis.analysis2();
            //OtherTests otherTests=new OtherTests();
            //otherTests.get方位角();
        } catch (Exception error) {
            System.out.println("系统错误：" + error.getMessage());
            System.out.println("错误堆栈信息如下：");
            error.printStackTrace();
        }
    }

    /**
     * 执行CLI命令行工具
     */
    private static void exeCLITools() {
        //因为是在win平台下，所以需要先打开cygwin64应用，然后在命令框内输入tippecanoe运行命令
        List<String> cliParms = new ArrayList<>();
//        cliParms.add("cmd");
//        cliParms.add("/C");
        cliParms.add("C:\\cygwin64\\bin\\mintty.exe");
        cliParms.add("/bin/sh");
        cliParms.add("-c");
        //在执行这个工具时，必须指明绝对路径，否则报错‘找不到文件或路径’；同时在这里因为是运行的Linux命令，所以一定要使用斜杠（Windows的路径使用的是反斜杠）
        cliParms.add("C:/cygwin64/home/CMCCJLJ/tippecanoe/tippecanoe -e E:/gislogs/vectortile/tile08 -pC -Z2 -z13 E:/gislogs/demoProvince2.geojson");
        //        cliParms.add("C:/cygwin64/home/CMCCJLJ/tippecanoe/tippecanoe --help");
        String[] cliCommand = cliParms.toArray(new String[cliParms.size()]);
        //在执行过程中，会弹出cmd的运行窗口，然后：如果报错，则窗口停留；否则开始执行过程，执行完毕后，窗口自动关闭；
        try {
            long timeStart = System.currentTimeMillis();
            Process subProcess = Runtime.getRuntime().exec(cliCommand);
            //上一句直接被执行过了，也就是没有等待
            long timeEndTippecanoe = System.currentTimeMillis();
            System.out.println("执行tippecanoe命令耗时：" + (timeEndTippecanoe - timeStart) / 1000 + "s");
            Thread.sleep(2000);
            //推测无法获取输出流的原因是，这不是win自带的cmd结果，而是cygwin64的结果，因此无法正常获取，需要进一步处理及确认。
            long timeEndBeforemain = System.currentTimeMillis();
            System.out.println("开始回到主线程执行时总共耗时：" + (timeEndBeforemain - timeStart) / 1000);
            System.out.println("InputStream");//这个还是可以执行
            InputStream streamTippecanoe = subProcess.getInputStream();
            InputStreamReader reader = new InputStreamReader(streamTippecanoe);
            BufferedReader br = new BufferedReader(reader);
            String line = null;
            while ((line = br.readLine()) != null) {
                System.out.println("content:" + line);
            }
//            int exitVal = subProcess.waitFor();
//            System.out.println("退出结果：" + exitVal);
//            subProcess.destroy();
            //最后这一句是被阻塞了的，也就是只有在tippecanoe命令完全执行完毕之后才会打印
            //也就是不论之前有没有写process的其他代码，都只有最后这一句被阻塞，前面的打印都没有被阻塞，为什么？
            System.out.println("CLI执行完毕!");
        } catch (Exception error) {
            System.out.println("CLI命令执行异常：" + error.getLocalizedMessage());
            error.printStackTrace();
        }
    }

    /**
     * 执行坐标转换（4326至3857）
     * 结果：shp中有一个要素（180.0,90.0）无法执行转换，会报错‘太靠近pole’;剔除这个要素之后其他的要素都可以转换成功
     * 并且能够在PostgreSQL里面看到几何
     */
    private static void testCoordTransform() {
        try {
            String wktPoint = "POINT(100.02715479879 33.462715497945)";
            String wktLine = "LINESTRING(108.32803893589 41.306670233001,99.950999898452 25.84722546391)";
            String wktPolygon = "POLYGON((100.02715479879 32.168082192159,102.76873121104 37.194305614622,"
                    + "107.0334056301 34.909658604412,105.96723702534 30.949603786713,"
                    + "100.02715479879 32.168082192159))";
//            String pointTest="POINT(180.0 90.0)";
            long timeStart = System.currentTimeMillis();
            CoordTransform myCoordTrans = new CoordTransform();
            //单个几何转换测试
            System.out.println("点转换结果" + myCoordTrans.projectGeometry(wktPoint));
            System.out.println("线转换结果" + myCoordTrans.projectGeometry(wktLine));
            System.out.println("面转换结果" + myCoordTrans.projectGeometry(wktPolygon));
//            System.out.println("面转换结果" + myCoordTrans.projectGeometry(pointTest));
            //shp文件转换测试
            //排除出错的那个点之后，可以转换成功，并且在PostGIS中可以看到转换后的结果。
            String pathShpSource = "E:\\0.myWork\\testdata\\country.shp";
            String pathShpTarget = "E:\\0.myWork\\testdata\\country2.shp";
            myCoordTrans.projectShp(pathShpSource, pathShpTarget);
            long timeTotal = System.currentTimeMillis() - timeStart;
            System.out.println("shp文件转换执行完毕。一共耗时" + timeTotal / 1000 + "s");
        } catch (Exception error) {
            System.out.println("坐标转换发生错误:");
            error.printStackTrace();
        }
    }

    /**
     * 矢量要素编辑操作
     * 1-根据属性查询；2-根据fid查询；
     * 3-矢量要素属性编辑
     * 4-根据空间范围查询符合条件的要素；
     * 5-矢量要素几何位置编辑
     */
    private static void testVectorOperation() {
        try {
            VectorOperation opraVector = new VectorOperation();
            String className = "country";
            /*//根据属性选择要素
            opraVector.queryVectorbyAttrs();
            //编辑要素属性
            opraVector.editVectorAttrs(className, fidFeature, fieldName2Alter, fieldValue2Alter);
            */
            /*//(3)根据空间范围选择矢量要素
            //这里的polygon字符串必须要闭合
            String wktPolygonStr = "POLYGON((117.110858 40.70836,117.286401 40.660719,"
                    + "117.389879 40.228141,117.389879 40.5617,117.110858 40.70836))";
            GeometryFactory geoFactory = JTSFactoryFinder.getGeometryFactory();
            WKTReader wktReader = new WKTReader(geoFactory);
            Geometry geoWKT = wktReader.read(wktPolygonStr);
            opraVector.queryVectorbySpatial(className, geoWKT);
            */
            // System.out.println("坐标参考系是："+geoWKT.getSRID());
            // 这里坐标参考是0，那么疑问是：在操作时用的是什么坐标系呢？
            /*//使用GeoJson的方式求交集
            String strGeoJson= BaseGeometryUtility.Wkt2GeoJson(wktPolygonStr);
            System.out.println("GeoJson结果是："+strGeoJson);
            opraVector.queryVectorbySpatial(className, strGeoJson);
            */
            //遗留的问题：我创建的几何是JTS的类型，而filter需要的是GeoTools的类型，
            //且这两者之间又不能直接转换，那么有什么方法可以执行呢？
            //(4)矢量要素几何编辑（两种方式都可以实现要素几何的编辑）
            String wktPoint = "POINT(121.472644 31.231706)";
            //方式一[使用wkt的几何格式]
            //GeometryFactory factoryGeo = JTSFactoryFinder.getGeometryFactory();
            //WKTReader readerWkt = new WKTReader(factoryGeo);
            //Geometry geoWKT = readerWkt.read(wktPoint);
            //方式二[使用GeoJson的几何格式]
            String strGeoJson = BaseGeometryUtility.Wkt2GeoJson(wktPoint);
            opraVector.editVectorGeometry("cities", 2, strGeoJson);
            System.out.println("矢量要素编辑 执行结束");
        } catch (Exception error) {
            System.out.println("执行过程发生异常：");
            error.printStackTrace();
        }
    }

}


